block the text_layout's "changed" handler when changing cursor visibility
authorMichael Natterer <mitch@imendio.com>
Wed, 25 May 2005 10:22:37 +0000 (10:22 +0000)
committerMichael Natterer <mitch@src.gnome.org>
Wed, 25 May 2005 10:22:37 +0000 (10:22 +0000)
2005-05-25  Michael Natterer  <mitch@imendio.com>

* gtk/gtktextview.c (blink_cb): block the text_layout's "changed"
handler when changing cursor visibility because it would expose
the whole paragraph where the cursor is. Instead, expose the
cursors' areas manually. (#173047).

(text_window_invalidate_cursors): new function which exposes the
cursors.

* gtk/gtkstyle.c (draw_insertion_cursor): added comment that the
same cursor size calculation is in text_window_invalidate_cursors().

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
gtk/gtkstyle.c
gtk/gtktextview.c

index 09bfe955c290332dc86cfcce8985d8e808e1389b..3b16a5bbbe770d0acd0684c1226377a178949169 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2005-05-25  Michael Natterer  <mitch@imendio.com>
+
+       * gtk/gtktextview.c (blink_cb): block the text_layout's "changed"
+       handler when changing cursor visibility because it would expose
+       the whole paragraph where the cursor is. Instead, expose the
+       cursors' areas manually. (#173047).
+
+       (text_window_invalidate_cursors): new function which exposes the
+       cursors.
+
+       * gtk/gtkstyle.c (draw_insertion_cursor): added comment that the
+       same cursor size calculation is in text_window_invalidate_cursors().
+
 2005-05-25  Matthias Clasen  <mclasen@redhat.com>
 
        * demos/gtk-demo/editable_cells.c (create_items_model): Also
index 09bfe955c290332dc86cfcce8985d8e808e1389b..3b16a5bbbe770d0acd0684c1226377a178949169 100644 (file)
@@ -1,3 +1,16 @@
+2005-05-25  Michael Natterer  <mitch@imendio.com>
+
+       * gtk/gtktextview.c (blink_cb): block the text_layout's "changed"
+       handler when changing cursor visibility because it would expose
+       the whole paragraph where the cursor is. Instead, expose the
+       cursors' areas manually. (#173047).
+
+       (text_window_invalidate_cursors): new function which exposes the
+       cursors.
+
+       * gtk/gtkstyle.c (draw_insertion_cursor): added comment that the
+       same cursor size calculation is in text_window_invalidate_cursors().
+
 2005-05-25  Matthias Clasen  <mclasen@redhat.com>
 
        * demos/gtk-demo/editable_cells.c (create_items_model): Also
index 09bfe955c290332dc86cfcce8985d8e808e1389b..3b16a5bbbe770d0acd0684c1226377a178949169 100644 (file)
@@ -1,3 +1,16 @@
+2005-05-25  Michael Natterer  <mitch@imendio.com>
+
+       * gtk/gtktextview.c (blink_cb): block the text_layout's "changed"
+       handler when changing cursor visibility because it would expose
+       the whole paragraph where the cursor is. Instead, expose the
+       cursors' areas manually. (#173047).
+
+       (text_window_invalidate_cursors): new function which exposes the
+       cursors.
+
+       * gtk/gtkstyle.c (draw_insertion_cursor): added comment that the
+       same cursor size calculation is in text_window_invalidate_cursors().
+
 2005-05-25  Matthias Clasen  <mclasen@redhat.com>
 
        * demos/gtk-demo/editable_cells.c (create_items_model): Also
index d2af4bf08283ff180a3ab977df7733636e435b32..8fa082a6b3dee386e255bdeb4aaf99fe5c29b0f7 100644 (file)
@@ -6628,7 +6628,11 @@ draw_insertion_cursor (GtkWidget        *widget,
   gint offset;
   
   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
-  
+
+  /* When changing the shape or size of the cursor here,
+   * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
+   */
+
   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
   
   stem_width = location->height * cursor_aspect_ratio + 1;
index d207cf68101f1c1b14abc56243d2047a26396e0c..91f1d4fac132c359dd074ca85a4be0911b0b4ce1 100644 (file)
@@ -408,6 +408,7 @@ static void           text_window_scroll          (GtkTextWindow     *win,
                                                    gint               dy);
 static void           text_window_invalidate_rect (GtkTextWindow     *win,
                                                    GdkRectangle      *rect);
+static void           text_window_invalidate_cursors (GtkTextWindow  *win);
 
 static gint           text_window_get_width       (GtkTextWindow     *win);
 static gint           text_window_get_height      (GtkTextWindow     *win);
@@ -4502,9 +4503,22 @@ blink_cb (gpointer data)
     text_view->blink_timeout = g_timeout_add (get_cursor_time (text_view) * CURSOR_ON_MULTIPLIER,
                                              blink_cb,
                                              text_view);
-  
-  gtk_text_layout_set_cursor_visible (text_view->layout,
-                                      !visible);
+
+  /* Block changed_handler while changing the layout's cursor visibility
+   * because it would expose the whole paragraph. Instead, we expose
+   * the cursor's area(s) manually below.
+   */
+  g_signal_handlers_block_by_func (text_view->layout,
+                                   changed_handler,
+                                   text_view);
+
+  gtk_text_layout_set_cursor_visible (text_view->layout, !visible);
+
+  g_signal_handlers_unblock_by_func (text_view->layout,
+                                     changed_handler,
+                                     text_view);
+
+  text_window_invalidate_cursors (text_view->text_window);
 
   GDK_THREADS_LEAVE ();
 
@@ -7357,6 +7371,71 @@ text_window_invalidate_rect (GtkTextWindow *win,
 #endif
 }
 
+static void
+text_window_invalidate_cursors (GtkTextWindow *win)
+{
+  GtkTextView *text_view = GTK_TEXT_VIEW (win->widget);
+  GtkTextIter  iter;
+  GdkRectangle strong;
+  GdkRectangle weak;
+  gboolean     draw_arrow;
+  gfloat       cursor_aspect_ratio;
+  gint         stem_width;
+  gint         arrow_width;
+
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter,
+                                    gtk_text_buffer_get_insert (text_view->buffer));
+
+  gtk_text_layout_get_cursor_locations (text_view->layout, &iter,
+                                        &strong, &weak);
+
+  /* cursor width calculation as in gtkstyle.c:draw_insertion_cursor(),
+   * ignoring the text direction be exposing both sides of the cursor
+   */
+
+  draw_arrow = (strong.x != weak.x || strong.y != weak.y);
+
+  gtk_widget_style_get (win->widget,
+                        "cursor-aspect-ratio", &cursor_aspect_ratio,
+                        NULL);
+
+  stem_width = strong.height * cursor_aspect_ratio + 1;
+  arrow_width = stem_width + 1;
+
+  /* round up to the next even number */
+  if (stem_width & 1)
+    stem_width++;
+
+  strong.x     -= stem_width / 2;
+  strong.width += stem_width;
+
+  if (draw_arrow)
+    {
+      strong.x     -= arrow_width;
+      strong.width += arrow_width * 2;
+    }
+
+  text_window_invalidate_rect (win, &strong);
+
+  if (draw_arrow) /* == have weak */
+    {
+      stem_width = weak.height * cursor_aspect_ratio + 1;
+      arrow_width = stem_width + 1;
+
+      /* round up to the next even number */
+      if (stem_width & 1)
+        stem_width++;
+
+      weak.x     -= stem_width / 2;
+      weak.width += stem_width;
+
+      weak.x     -= arrow_width;
+      weak.width += arrow_width * 2;
+
+      text_window_invalidate_rect (win, &weak);
+    }
+}
+
 static gint
 text_window_get_width (GtkTextWindow *win)
 {